package cn.jh.common.proxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * 快银支付接口
 */
public class CongMingPayProxyService {

    private static final Logger log = LoggerFactory.getLogger(CongMingPayProxyService.class);

    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36";
    private static final String DEF_CHARSETS = StandardCharsets.UTF_8.name();
    private static final int DEF_CONN_TIMEOUT = 30000;
    private static final int DEF_READ_TIMEOUT = 30000;
    private static final String DEF_REQUEST_METHOD = "POST";

    // 预支付
    private static final String PRE_PAY = "http://pay.congmingpay.com/pay/prepay.do";
    // 条码支付
    private static final String MICRO_PAY = "http://pay.congmingpay.com/pay/micropay.do";
    // 公众号支付
    private static final String BUY_PAY = "http://pay.congmingpay.com/pay/buypay.do";
    // 小程序支付
    private static final String MINI_APP_PAY = "http://pay.congmingpay.com/pay/miniapppay.do";
    // 查询接口
    private static final String QUERY = "http://pay.congmingpay.com/pay/query.do";

    /**
     * Http创建远程连接
     * @param url 请求地址
     * @param method 请求方式：GET/POST
     * @return String
     */
    private static String HttpURLConnectionUtil(String url, String method) throws IOException {
        HttpURLConnection conn = null;
        BufferedReader reader = null;
        StringBuilder sb = new StringBuilder();
        String rs = null;

        try {
            URL urls = new URL(url);
            conn = (HttpURLConnection) urls.openConnection();
            if (null == method || method.equals("GET")) {
                conn.setRequestMethod("GET");
            } else {
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);
            }
            conn.setRequestProperty("User-agent", USER_AGENT);
            conn.setUseCaches(false);
            conn.setConnectTimeout(DEF_CONN_TIMEOUT);
            conn.setReadTimeout(DEF_READ_TIMEOUT);
            conn.setInstanceFollowRedirects(false);
            conn.connect();
            if ("POST".equals(method)) {
                try {
                    DataOutputStream out = new DataOutputStream(conn.getOutputStream());
                    out.writeBytes(url);
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
            InputStream is = conn.getInputStream();
            reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
            String strRead;
            while ((strRead = reader.readLine()) != null) {
                sb.append(strRead);
            }
            rs = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                reader.close();
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        return rs;
    }

    /**
     * 将map型转为请求参数型
     * @param map
     * @return
     */
    private static String urlEncode(Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry i : map.entrySet()) {
            try {
                sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", DEF_CHARSETS)).append("&");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return sb.substring(0, sb.length() - 1);
    }

    /**
     * 公众号支付
     * @param shopId 商户id，此shopId为快银通道方生成的，请区别本项目中的shopId
     * @param money 交易金额
     * @param orderId 商户发起api支付的订单号
     * @param sign 加密sign
     * @param redirectUrl 回调地址，可带参数，参数会原样返回
     * @return
     */
    public static String buyPay(String shopId, String money, String orderId, String sign, String redirectUrl) throws RuntimeException {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("shopId", shopId);
            map.put("money", money);
            map.put("orderId", orderId);
            map.put("type", "");
            map.put("device", "");
            map.put("goodsMsg", "");
            map.put("sign", sign);
            map.put("redirectUrl", redirectUrl);

            String params = urlEncode(map);
            String url = BUY_PAY + "?" + params;
            return HttpURLConnectionUtil(url, DEF_REQUEST_METHOD);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 预支付接口
     * 预支付接口用于提前获取需要支付的金额，客户扫描二维码即完成支付：反扫描
     * 响应内容为字符串形式，将字符串生成二维码，既可以完成支付。
     * 微信：weixin://wxpay/bizpayurl?pr=CBfzgiT
     * 支付宝：https://qr.alipay.com/bax04600gg0zrdo6xevx003b
     * @param shopId 商户id，此shopId为快银通道方生成的，请区别本项目中的shopId
     * @param orderId 商户发起api支付的订单号
     * @param money 交易金额
     * @param type 支付类型：微信-weixin，支付宝-alipay
     * @param redirectUrl 回调地址，可带参数，参数会原样返回
     * @param sign 加密sign
     * @return String
     */
    public static String prePay(String shopId, String orderId, String money, String type, String redirectUrl, String sign) throws RuntimeException {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("shopId", shopId);
            map.put("orderId", orderId);
            map.put("money", money);
            map.put("type", type);
            map.put("redirectUrl", redirectUrl);
            map.put("sign", sign);

            String params = urlEncode(map);

            String url = PRE_PAY + "?" + params;
            return HttpURLConnectionUtil(url, DEF_REQUEST_METHOD);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 条码支付接口
     * 条码支付接口用于商户使用扫码枪等扫码工具扫描客户手机付款吗，从而实现支付功能：主扫码
     * @param shopId 商户id，此shopId为快银通道方生成的，请区别本项目中的shopId
     * @param orderId 商户发起api支付的订单号
     * @param money 交易金额
     * @param authCode 支付授权码
     * @param sign 加密sign
     * @return JSON
     */
    public static String microPay(String shopId, String orderId, String money, String authCode, String sign) throws RuntimeException {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("shopId", shopId);
            map.put("orderId", orderId);
            map.put("money", money);
            map.put("authCode", authCode);
            map.put("sign", sign);

            String params = urlEncode(map);

            String url = MICRO_PAY + "?" + params;
            return HttpURLConnectionUtil(url, DEF_REQUEST_METHOD);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 小程序支付接口
     * @param shopId
     * @param money
     * @param appid
     * @param appOpenid
     * @param sign
     * @param redirectUrl
     * @return
     * @throws Exception
     */
    public static String miniAppPay(String shopId, String money, String appid, String appOpenid, String sign, String redirectUrl) throws RuntimeException {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("shopId", shopId);
            map.put("money", money);
            map.put("appid", appid);
            map.put("appOpenid", appOpenid);
            map.put("sign", sign);
            map.put("redirectUrl", redirectUrl);

            String params = urlEncode(map);
            String url = MINI_APP_PAY + "?" + params;
            return HttpURLConnectionUtil(url, DEF_REQUEST_METHOD);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 查询接口
     * @param shopId 商户id，此shopId为快银通道方生成的，请区别本项目中的shopId
     * @param orderId 商户发起api支付的订单号
     * @return JSON
     * @throws Exception
     */
    public static String query(String shopId, String orderId) throws RuntimeException {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("shopId", shopId);
            map.put("orderId", orderId);

            String params = urlEncode(map);
            String url = QUERY + "?" + params;
            return HttpURLConnectionUtil(url, DEF_REQUEST_METHOD);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
}
